import { Observable, Observer, filter, map } from 'rxjs';
import { ReactiveProperty } from './ReactiveProperty';
import { _decorator, tween, __private, ITweenOption, log, director } from 'cc';
const { ccclass, property } = _decorator;


export function TweenToStart<T>(target: T, duration: number, props?: __private._cocos_tween_tween__ConstructorType<unknown>, opts?: ITweenOption)
    : Observable<{ target: T, ratio?: number, status: string }> {
    return _TweenToStart(target, duration, props, opts).observable;
}

// 可随时中断的Tween
export function TweenToStartWithSkip<T>(target: T, duration: number, props?: __private._cocos_tween_tween__ConstructorType<unknown>, opts?: ITweenOption)
    : { observable: Observable<{ target: T, ratio?: number, status: string }>, skip: () => void } {
    return _TweenToStart(target, duration, props, opts);
}

// 封装了一个极简的帧序列
export function TweenSimpleWithSkip(duration: number) {
    let { observable, skip } = _TweenToStart(director.getScene(), duration)
    return { observable: observable.pipe(filter(_ => _.status == 'update'), map(_ => _.ratio)), skip };
}

function _TweenToStart<T>(target: T, duration: number, props?: __private._cocos_tween_tween__ConstructorType<unknown>, opts?: ITweenOption): { observable: Observable<any>, skip: () => void } {
    let needSkip = ReactiveProperty.Create(false);
    let skip = () => needSkip.value = true;
    const observable = new Observable((observer: Observer<{ target: T, ratio?: number, status: string }>) => {
        if (opts == null) opts = {};
        opts.onStart = (target: unknown) => observer.next({ target: <T>target, status: 'start' });
        opts.onUpdate = (target: unknown, ratio: number) => observer.next({ target: <T>target, ratio, status: 'update' });
        opts.onComplete = (target: unknown) => {
            observer.next({ target: <T>target, status: 'complete' });
            observer.complete();
        }
        let _t = needSkip.value ? null : tween(target).to(duration, props, opts).start();
        needSkip.subscribeWhenTrue(() => {
            observer.next({ target: <T>target, status: 'skip' });
            observer.complete();
        });
        return () => {
            _t && _t.stop();
        }
    });
    return { observable, skip };
}
